package com.ruoyi.common.filter

import com.ruoyi.common.utils.html.EscapeUtil
import org.apache.commons.io.IOUtils
import org.apache.commons.lang3.StringUtils
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import java.io.ByteArrayInputStream
import java.io.IOException
import javax.servlet.ReadListener
import javax.servlet.ServletInputStream
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletRequestWrapper

/**
 * XSS过滤处理
 *
 * @author ruoyi
 */
class XssHttpServletRequestWrapper
/**
 * @param request
 */
    (request: HttpServletRequest?) : HttpServletRequestWrapper(request) {
    override fun getParameterValues(name: String?): Array<String?> {
        val values: Array<String>? = super.getParameterValues(name)
        if (values != null) {
            val length = values.size
            val escapesValues = arrayOfNulls<String>(length)
            for (i in 0 until length) {
                // 防xss攻击和过滤前后空格
                escapesValues[i] = EscapeUtil.clean(values[i])?.trim()
            }
            return escapesValues
        }
        return super.getParameterValues(name)
    }

    @Throws(IOException::class)
    override fun getInputStream(): ServletInputStream {
        // 非json类型，直接返回
        if (!isJsonRequest) {
            return super.getInputStream()
        }

        // 为空，直接返回
        var json: String = IOUtils.toString(super.getInputStream(), "utf-8")
        if (StringUtils.isEmpty(json)) {
            return super.getInputStream()
        }

        // xss过滤
        json = EscapeUtil.clean(json)!!.trim()
        val jsonBytes: ByteArray = json.toByteArray()
        val bis = ByteArrayInputStream(jsonBytes)
        return object : ServletInputStream() {

            @Throws(IOException::class)
            override fun available(): Int {
                return jsonBytes.size
            }

            override fun isFinished(): Boolean {
                return true
            }

            override fun isReady(): Boolean {
                return true
            }

            override fun setReadListener(readListener: ReadListener?) {
            }

            @Throws(IOException::class)
            override fun read(): Int {
                return bis.read()
            }
        }
    }

    private val isJsonRequest: Boolean
        /**
         * 是否是Json请求
         */
        get() {
            val header: String = super.getHeader(HttpHeaders.CONTENT_TYPE)
            return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE)
        }
}
